/*
 * @features: 功能
 * @description: 说明
 * @Date: 2021-10-07 11:28:23
 * @Author: judu233(769471424@qq.com)
 * @LastEditTime: 2021-10-27 22:22:41
 * @LastEditors: judu233
 */

import c3d from "../../tool/cc";
import { resLoader } from "../../tool/other/ResLoader";
import { ILanguageData } from "../../language/LanguageBase";

export enum LanguageEvent {
    /** 语种变化事件 */
    CHANGE = 'LanguageEvent.CHANGE',
    /** 语种资源释放事件 */
    RELEASE_RES = "LanguageEvent.RELEASE_RES"
}
const DEFAULT_LANGUAGE = "zh";
type LanguageType = "zh" | "en" | "tr";
type LanguageCom = c3d.Label | c3d.RichText | c3d.Sprite | c3d.Button;

export default class LanguageManager {
    /**识别多语言id的前缀 */
    languageSign = `$`;
    /**保存的文本组件引用 */
    languageCom: Map<string, LanguageCom> = new Map();

    /**当前语言 */
    private _currentLang: LanguageType = DEFAULT_LANGUAGE;
    /**获取当前语种 */
    get curLanguage() { return this._currentLang; }

    /**支持的语言 */
    private _supportLanguages: Array<LanguageType> = ["zh", "en", "tr"];
    /** 设置多语言系统支持哪些语种 */
    set supportLanguages(supportLanguages: Array<LanguageType>) { this._supportLanguages = supportLanguages; }
    /**  * 获取支持的多语种数组  */
    get supportLanguages() { return this._supportLanguages; }

    /**语言表 */
    trans: ILanguageData = {} as any;

    /** 默认的多语言json路径 */
    private _langjsonPath: string = "lang_json";
    /**默认的多语言图片路径 */
    private _langTexturePath: string = "lang_texture";

    /**  获取下一个语种   */
    getNextLang() {
        let supportLangs = this.supportLanguages;
        let index = supportLangs.indexOf(this._currentLang);
        let newLanguage = supportLangs[(index + 1) % supportLangs.length];
        return newLanguage;
    }

    /**
     * 改变语种，会自动下载对应的语种，下载完成回调
     * @param language 
     */
    setLanguage(language: LanguageType, callback: (success: boolean) => void) {
        if (!language) {
            language = DEFAULT_LANGUAGE;
        }
        let index = this.supportLanguages.indexOf(language);
        if (index < 0) {
            c3d.warn("当前不支持该语种" + language + " 将自动切换到 zh 语种！");
            language = DEFAULT_LANGUAGE;
        }
        if (language === this._currentLang) {
            callback(false);
            return;
        }

        this.loadLanguageAssets(language, (err: any, lang: string) => {
            if (err) {
                c3d.error("语言资源包下载失败", err);
                callback(false);
                return;
            }
            c3d.Out.logBusiness(`当前语言为【${language}】`);
            this._currentLang = language;
            this.updateLanguage(language);
            // this.dispatchEvent(LanguageEvent.CHANGE, lang);
            callback(true);
        });
    }
    /**
   * 刷新语言文字
   * @param lang 
   */
    updateLanguage(lang: LanguageType) {
        let lanjson = resLoader.get(`${this._langjsonPath}/${lang}`, c3d.JsonAsset);
        if (lanjson && lanjson.json) {
            this.trans = lanjson.json as any;
            for (let com of this.languageCom) {
                if (com instanceof c3d.Label || com instanceof c3d.RichText) {
                    com.string = this.trans[com.i18Id];
                } else if (com instanceof c3d.Sprite) {
                    this.changeSpreite(com);
                } else if (com instanceof c3d.Button) {
                    this.changeButton(com);
                }
            }
        }
        else {
            c3d.warn("没有找到指定语言内容配置", lang);
        }
    }

    /**
     * 根据id获取图片
     * @param namePath 多语言id
     * @returns 图片
     */
    getSf(namePath: string) {
        let path = `language/texture/${this.curLanguage}/${namePath}/spriteFrame`;
        let res = resLoader.get(path, c3d.SpriteFrame);
        if (!res)
            c3d.Out.erroring("[LanguageSprite] 资源不存在 " + path);
        return res;
    }

    /**
     * 设置sprite组件切换图片
     * @param sp sprite组件
     */
    changeSpreite(sp: c3d.Sprite) {
        // 获取语言标记
        sp.spriteFrame = this.getSf(this.trans[sp.i18Id]);
        /** 修改节点为原始图片资源大小 */
        let isRawSize = true;
        if (isRawSize) {
            //@ts-ignore
            sp.getComponent(c3d.UITransform)?.setContentSize(res?._originalSize);
        }
    }

    /**
     * 设置按钮的切换图片
     * @param btn 按钮
     */
    changeButton(btn: c3d.Button) {
        let sp = btn.getComponent(c3d.Sprite);
        if (sp)
            sp.spriteFrame = this.getSf(this.trans[btn.i18Id]);
        btn.normalSprite = this.getSf(this.trans[btn.i18Id]);
        btn.pressedSprite = this.getSf(this.trans[btn.i18nPressId]);
        btn.hoverSprite = this.getSf(this.trans[btn.i18nHoverId]);
    }

    /**
     * 设置多语言资源目录
     * @param langjsonPath 多语言json目录
     * @param langTexturePath 多语言图片目录
     */
    setAssetsPath(langjsonPath: string, langTexturePath: string) {
        this._langjsonPath = langjsonPath ?? (c3d.warn(`语言包setAssetsPath.langjsonPath 为空`), '');
        this._langTexturePath = langTexturePath ?? (c3d.warn(`语言包setAssetsPath.langTexturePath 为空`), '');
    }

    /**
     * 记录多语言组件
     * @param com 要设置的多语言组件
     */
    setLangByCom(com: LanguageCom) {
        if (com instanceof c3d.Label || com instanceof c3d.RichText) {
            if (com.string?.[0] == this.languageSign) {
                com.i18Id = com.string.substr(1);
                this.languageCom.set(com.i18Id, com);
            }
        } else if (com instanceof c3d.Sprite) {
            if (com.spriteFrame?.name[0] == this.languageSign) {
                com.i18Id = com.spriteFrame.name.substr(1);
                this.languageCom.set(com.i18Id, com);
            }
        } else if (com instanceof c3d.Button) {
            if (com.transition == c3d.Button.Transition.SPRITE && com.normalSprite?.name[0] == this.languageSign) {
                com.i18Id = com.normalSprite?.name.substr(1);
                com.i18nHoverId = com.hoverSprite?.name.substr(1);
                com.i18nPressId = com.pressedSprite?.name.substr(1);
                this.languageCom.set(com.i18Id, com);
            }
        }
    }

    /**
     * 根据data获取对应语种的字符
     */
    getLangByID(labId: string): string {
        return this.trans[labId] || "";
    }

    /**
     * 下载语言包素材资源
     * 包括语言json配置和语言纹理包
     */
    loadLanguageAssets(lang: LanguageType, callback: Function) {
        let lang_texture_path = `${this._langTexturePath}/${lang}`;
        let lang_json_path = `${this._langjsonPath}/${lang}`;
        return resLoader.loadDir(lang_texture_path, (err: any) => {
            if (err) {
                c3d.error(err);
                callback(err);
                return;
            }
            c3d.Out.logBusiness(lang_texture_path, "下载语言包 textures 资源");
            resLoader.load(lang_json_path, c3d.JsonAsset, (err) => {
                if (err) {
                    c3d.error(err);
                    callback(err);
                    return;
                }
                c3d.Out.trace(lang_json_path, "下载语言包 json 资源");
                callback(err, lang);
            })
        })
    }

    /**
     * 释放不需要的语言包资源
     */
    releaseLanguageAssets(lang: LanguageType) {
        let langpath = `${this._langTexturePath}/${lang}`;
        resLoader.releaseDir(langpath);
        c3d.Out.logBusiness(langpath, "释放语言图片资源");

        let langjsonpath = `${this._langjsonPath}/${lang}`;
        resLoader.release(langjsonpath);
        c3d.Out.logBusiness(langjsonpath, "释放语言文字资源");
        // this.dispatchEvent(LanguageEvent.RELEASE_RES, lang);
    }

    /**移除组件的引用 */
    releasrLanguCom(com: LanguageCom) {
        let removeId = com.i18Id;
        if (removeId)
            this.languageCom.delete(removeId);
    }


    
    /**
     * @description 把语言包转换成i18n.xxx形式
     * @param param 语言包配置
     * @param bundle bundle
     * @example
     * export let TANK_LAN_ZH = {
     * language: cc.sys.LANGUAGE_CHINESE,
     * data: {
     * title: `坦克大战`,
     * player: '单人模式 ',
     * palyers: '双人模式',
     * }
     * }
     * //以上是坦克大战的语言包,assetBundle为tankBattle
     * Manager.makeLanguage("title","tankBattle"); //=> i18n.tankBattle.title 指向游戏特定的语言包
     * Manager.makeLanguage("title"); //=> i18n.title 指向的大厅的公共语言包
     */
    //  makeLanguage(param: string | (string | number)[], bundle: BUNDLE_TYPE = Macro.BUNDLE_RESOURCES): (string | number)[] | string {
    //     if (typeof param == "string") {
    //         if (bundle) {
    //             return `${Macro.USING_LAN_KEY}${bundle}.${param}`;
    //         }
    //         return `${Macro.USING_LAN_KEY}${param}`;
    //     }
    //     if (typeof param[0] == "string" && param instanceof Array) {
    //         if (bundle) {
    //             param[0] = `${Macro.USING_LAN_KEY}${bundle}.${param[0]}`;
    //         } else {
    //             param[0] = `${Macro.USING_LAN_KEY}${param[0]}`;
    //         }
    //     }
    //     return param;
    // }

    // /** 获取语言包    */
    // getLanguage(param: string | (string | number)[], bundle: BUNDLE_TYPE | null = null): any {
    //     let key = "";
    //     if (typeof param == "string") {
    //         if (bundle) {
    //             key = `${Macro.USING_LAN_KEY}${bundle}.${param}`;
    //         } else {
    //             key = `${Macro.USING_LAN_KEY}${param}`;
    //         }
    //         return this.language.get([key]);
    //     }
    //     if (typeof param[0] == "string" && param instanceof Array) {
    //         if (bundle) {
    //             param[0] = `${Macro.USING_LAN_KEY}${bundle}.${param[0]}`;
    //         } else {
    //             param[0] = `${Macro.USING_LAN_KEY}${param[0]}`;
    //         }
    //         return this.language.get(param);
    //     }
    //     Log.e(`传入参数有误`);
    //     return "";
    // }
}

